package com.cskaoyan.wordmemorize.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.listener.ReadListener;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cskaoyan.wordmemorize.common.constant.ResultCodeEnum;
import com.cskaoyan.wordmemorize.common.aspect.operate.OperateLog;
import com.cskaoyan.wordmemorize.common.aspect.operate.OperateLogConstant;
import com.cskaoyan.wordmemorize.common.exception.BusinessException;
import com.cskaoyan.wordmemorize.converter.VocConverter;
import com.cskaoyan.wordmemorize.dao.entity.*;
import com.cskaoyan.wordmemorize.dao.mapper.*;
import com.cskaoyan.wordmemorize.dto.admin.*;
import com.cskaoyan.wordmemorize.dto.app.DisplayBookVocDTO;
import com.cskaoyan.wordmemorize.dto.app.DisplayChapterDTO;
import com.cskaoyan.wordmemorize.dto.app.UserBookStatisticsDTO;
import com.cskaoyan.wordmemorize.excel.ValidateVocExcelListener;
import com.cskaoyan.wordmemorize.excel.VocExcelListener;
import com.cskaoyan.wordmemorize.request.*;
import com.cskaoyan.wordmemorize.service.*;
import com.cskaoyan.wordmemorize.service.GZVocChapBookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;


// todo【后台管理-物料管理-单词管理相关接口】的部分

@Service
public class VocServiceImpl implements VocService {


    @Autowired
    VocMapper vocMapper;

    @Autowired
    VocConverter vocConverter;


    @Autowired
    VocMeaningMapper vocMeaningMapper;

    @Autowired
    ExampleSentenceMapper exampleSentenceMapper;

    @Autowired
    VocChapBookMapper vocChapBookMapper;

    @Autowired
    VocChapterMapper vocChapterMapper;


    @Autowired
    VocBookMapper vocBookMapper;

    @Autowired
    GZVocMeaningService gzVocMeaningService;

    @Autowired
    GZExampleSentenceService gzExampleSentenceService;

    @Autowired
    GZVocChapBookService gzVocChapBookService;

    @Autowired
    FileUploadService fileUploadService;

    // todo 分页查询单词列表
    @Override
    public PageDTO<VocDTO> getVocabularies(VocPageRequest pageQuery) {

        if (pageQuery.getPageNum() == null || pageQuery.getCount() == null) {
            throw new BusinessException(ResultCodeEnum.FAIL);
        }

        Page<VocDO> pageParam = new Page<>(pageQuery.getPageNum(), pageQuery.getCount());

        Page<VocDO> vocDOPage = vocMapper.getVocabularyInfo(
                pageQuery.getBookId() != null ? Long.parseLong(pageQuery.getBookId()) : null,
                pageQuery.getChapterId() != null ? Long.parseLong(pageQuery.getChapterId()) : null,
                pageQuery.getKeyword(),
                pageParam
        );

        return vocConverter.vocList2Page(vocDOPage.getRecords(), vocDOPage.getTotal());
    }

    // todo 添加单词
    @Transactional
    @OperateLog(dataType = "单词", operateType = OperateLogConstant.OPERATE_ADD)
    @Override
    public void addVoc(VocCommand command) {

        // 判断要添加的单词是否存在
        LambdaQueryWrapper<VocDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(VocDO::getContent, command.getContent());

        VocDO vocDO = vocMapper.selectOne(queryWrapper);
        if (vocDO != null) {
            throw new BusinessException(ResultCodeEnum.VOC_EXISTED);
        }

        // 保存单词
        VocDO voc = vocConverter.command2VocDO(command);
        // 保存基本的单词数据
        vocMapper.insert(voc);


        // 保存单词释义
        List<VocMeaningCommand> interpretations = command.getInterpretations();
        List<VocMeaningDO> vocMeaningDOs = vocConverter.commands2VocMeaningDOs(interpretations);

        if (!CollectionUtils.isEmpty(vocMeaningDOs)) {

            vocMeaningDOs.forEach(vocMeaningDO -> {

                // 设置释义多对应的单词id
                vocMeaningDO.setVocId(voc.getId());
                vocMeaningMapper.insert(vocMeaningDO);
            });
        }

        // 保存例句
        List<ExampleSentenceCommand> examples = command.getExamples();
        List<ExampleSentenceDO> exampleSentenceDOs = vocConverter.commands2ExampleSentenceDOs(examples);
        if (!CollectionUtils.isEmpty(exampleSentenceDOs)) {
            exampleSentenceDOs.forEach(exampleSentenceDO -> {

                // 设置例句对应的单词id
                exampleSentenceDO.setVocId(voc.getId());
                exampleSentenceMapper.insert(exampleSentenceDO);
            });
        }


        // 保存单词-章节-书籍关系
        List<VocChapBookCommand> relations = command.getRelations();
        List<VocChapBookDO> vocChapBookDOs = vocConverter.commands2VocChapBookDOs(relations);
        if (!CollectionUtils.isEmpty(vocChapBookDOs)) {
            vocChapBookDOs.forEach(vocChapBookDO -> {

                // 设置单词id
                vocChapBookDO.setVocId(voc.getId());
                vocChapBookMapper.insert(vocChapBookDO);


                // 修改章节中包含的单词数量
                if (vocChapBookDO.getChapterId() != null) {

                    LambdaUpdateWrapper<VocChapterDO> chapterWrapper = new LambdaUpdateWrapper<>();
                    chapterWrapper.eq(VocChapterDO::getId, vocChapBookDO.getChapterId())
                            .setSql("voc_count = voc_count + 1");
                    vocChapterMapper.update(null, chapterWrapper);

                }

                // 书籍中包含的单词数量
                LambdaUpdateWrapper<VocBookDO> vocBookWrapper = new LambdaUpdateWrapper<>();
                vocBookWrapper.eq(VocBookDO::getId, vocChapBookDO.getBookId())
                        .setSql("voc_count = voc_count + 1");

                vocBookMapper.update(null, vocBookWrapper);
            });
        }

    }

    // todo 修改单词
    @OperateLog(dataType = "单词", operateType = OperateLogConstant.OPERATE_UPDATE)
    @Override
    @Transactional
    public void updateVoc(VocCommand command) {

        // todo 更新单词表基本信息
        VocDO vocDO = vocConverter.command2VocDO(command);
        vocMapper.updateById(vocDO);

        // todo 更新释义
        if (command.getInterpretations() != null && !command.getInterpretations().isEmpty()) {

            List<VocMeaningCommand> interpretations = command.getInterpretations();
            List<VocMeaningDO> vocMeaningDOS = vocConverter.commands2VocMeaningDOs(interpretations);
            gzVocMeaningService.updateBatchById(vocMeaningDOS);

        }

        // todo 更新例句
        if (command.getExamples() != null && !command.getExamples().isEmpty()) {

            List<ExampleSentenceCommand> examples = command.getExamples();
            List<ExampleSentenceDO> exampleSentenceDOs = vocConverter.commands2ExampleSentenceDOs(examples);
            gzExampleSentenceService.updateBatchById(exampleSentenceDOs);
        }

        // todo 更新书籍
        if (!CollectionUtils.isEmpty(command.getRelations())) {
            List<VocChapBookCommand> relations = command.getRelations();
            System.out.println("relations = " + relations);
            List<VocChapBookDO> vocChapBookDOs = vocConverter.commands2VocChapBookDOs(command.getRelations());

            System.out.println("vocChapBookDOs = " + vocChapBookDOs);
            LambdaUpdateWrapper<VocBookDO> vocBookWrapper = new LambdaUpdateWrapper<>();
            LambdaUpdateWrapper<VocChapterDO> chapterWrapper = new LambdaUpdateWrapper<>();
            vocChapBookDOs.forEach(newVocChapBookDO -> {

                        // todo:前端新增数据无id,直接插入
                        if (newVocChapBookDO.getId() == null) {
                            if (newVocChapBookDO.getBookId() != null) {
                                vocBookWrapper.clear();
                                vocBookWrapper.eq(VocBookDO::getId, newVocChapBookDO.getBookId())
                                        .setSql("voc_count = voc_count + 1");
                                vocBookMapper.update(vocBookWrapper);
                            }
                            if (newVocChapBookDO.getChapterId() != null) {
                                chapterWrapper.clear();
                                chapterWrapper.eq(VocChapterDO::getId, newVocChapBookDO.getChapterId())
                                        .setSql("voc_count = voc_count + 1");
                                vocChapterMapper.update(chapterWrapper);
                            }
                            vocChapBookMapper.insert(newVocChapBookDO);
                        } else {
                            // todo:已存在id,做修改，oldVocChapBookDO为数据库中单词章节书籍关系，newVocChapBookDO为前端传入单词章节书籍关系
                            VocChapBookDO oldVocChapBookDO = vocChapBookMapper.selectById(newVocChapBookDO.getId());

                            // todo:如果修改了书籍,将原书籍单词数量减1，新书籍单词数加1
                            if (!newVocChapBookDO.getBookId().equals(oldVocChapBookDO.getBookId())) {
                                vocBookWrapper.clear();
                                vocBookWrapper.eq(VocBookDO::getId, oldVocChapBookDO.getBookId())
                                        .setSql("voc_count = voc_count - 1");
                                vocBookMapper.update(vocBookWrapper);
                                vocBookWrapper.clear();
                                vocBookWrapper.eq(VocBookDO::getId, newVocChapBookDO.getBookId())
                                        .setSql("voc_count = voc_count + 1");
                                vocBookMapper.update(vocBookWrapper);

                            }
                            // todo:如果修改了章节，将原章节单词数量减1，新章节单词数加1
                            if (!newVocChapBookDO.getChapterId().equals(oldVocChapBookDO.getChapterId())) {
                                chapterWrapper.clear();
                                chapterWrapper.eq(VocChapterDO::getId, oldVocChapBookDO.getChapterId())
                                        .setSql("voc_count = voc_count - 1");
                                vocChapterMapper.update(chapterWrapper);
                                chapterWrapper.clear();
                                chapterWrapper.eq(VocChapterDO::getId, newVocChapBookDO.getChapterId())
                                        .setSql("voc_count = voc_count + 1");
                                vocChapterMapper.update(chapterWrapper);
                            }

                            // todo:根据前端传入单词章节书籍关系修改数据库中单词章节书籍关系
                            oldVocChapBookDO.setChapterId(newVocChapBookDO.getChapterId());
                            oldVocChapBookDO.setChapterName(newVocChapBookDO.getChapterName());
                            oldVocChapBookDO.setBookId(newVocChapBookDO.getBookId());
                            oldVocChapBookDO.setBookName(newVocChapBookDO.getBookName());
                            vocChapBookMapper.updateById(oldVocChapBookDO);
                        }
                    }
            );
        }
    }

    // todo:删除指定单词
    @OperateLog(dataType = "单词", operateType = OperateLogConstant.OPERATE_SINGLE_DELETE)
    @Transactional
    @Override
    public DeleteVocOperateDTO deleteVocabulary(Long vocId) {
        LambdaQueryWrapper<VocDO> vocQueryWrapper = new LambdaQueryWrapper<>();
        vocQueryWrapper.eq(VocDO::getId, vocId);
        VocDO vocDO = vocMapper.selectOne(vocQueryWrapper);
        // todo:若数据库中单词不存在，抛出异常
        if (vocDO == null) {
            throw new BusinessException(ResultCodeEnum.VOC_NOT_EXISTED);
        }
        // todo:删除voc表中基本单词数据
        vocMapper.deleteById(vocId);
        // todo:删除voc_meaning表中单词释义
        LambdaQueryWrapper<VocMeaningDO> vocMeaningQueryWrapper = new LambdaQueryWrapper<>();
        vocMeaningQueryWrapper.eq(VocMeaningDO::getVocId, vocId);
        vocMeaningMapper.delete(vocMeaningQueryWrapper);
        // todo:删除单词例句表中例句
        LambdaQueryWrapper<ExampleSentenceDO> exampleSentenceQueryWrapper = new LambdaQueryWrapper<>();
        exampleSentenceQueryWrapper.eq(ExampleSentenceDO::getVocId, vocId);
        exampleSentenceMapper.delete(exampleSentenceQueryWrapper);
        // todo：根据voc_chap_book表对voc_chapter表和voc_book表中voc_count减1，然后删除voc_chap_book表中数据
        LambdaQueryWrapper<VocChapBookDO> vocChapBookQueryWrapper = new LambdaQueryWrapper<>();
        vocChapBookQueryWrapper.eq(VocChapBookDO::getVocId, vocId);
        VocChapBookDO vocChapBookDO = vocChapBookMapper.selectOne(vocChapBookQueryWrapper);
        if (vocChapBookDO == null) {
            return vocConverter.toDeleteVocOperateDTO(vocDO);
        }
        // todo:修改书籍中单词数量
        LambdaUpdateWrapper<VocBookDO> vocBookUpdateWrapper = new LambdaUpdateWrapper<>();
        vocBookUpdateWrapper.eq(VocBookDO::getId, vocChapBookDO.getBookId())
                .setSql("voc_count = voc_count - 1");
        vocBookMapper.update(vocBookUpdateWrapper);
        // todo:修改章节中单词数量
        LambdaUpdateWrapper<VocChapterDO> vocChapterUpdateWrapper = new LambdaUpdateWrapper<>();
        vocChapterUpdateWrapper.eq(VocChapterDO::getId, vocChapBookDO.getChapterId())
                .setSql("voc_count = voc_count - 1");
        vocChapterMapper.update(vocChapterUpdateWrapper);
        // todo:删除voc_chap_book中数据
        vocChapBookMapper.delete(vocChapBookQueryWrapper);
        return vocConverter.toDeleteVocOperateDTO(vocDO);
    }

    // todo:批量删除单词
    @OperateLog(dataType = "单词", operateType = OperateLogConstant.OPERATE_BATCH_DELETE)
    @Transactional
    @Override
    public List<DeleteVocOperateDTO> deleteVocabularies(BatchDeleteCommand command) {
        List<String> ids = command.getIds();
        // todo:将String类型的单词id转换为Long类型
        List<Long> list = ids.stream().map(Long::valueOf).collect(Collectors.toList());
        LambdaQueryWrapper<VocDO> vocQueryWrapper = new LambdaQueryWrapper<>();
        vocQueryWrapper.in(VocDO::getId, list);
        List<VocDO> vocDOs = vocMapper.selectList(vocQueryWrapper);
        // todo:若数据库中有单词不存在，抛出异常
        if (ids.size() != vocDOs.size()) {
            throw new BusinessException(ResultCodeEnum.VOC_NOT_EXISTED);
        }
        // todo:删除voc表中基本单词数据
        vocMapper.delete(vocQueryWrapper);
        // todo:删除voc_meaning表中单词释义
        LambdaQueryWrapper<VocMeaningDO> vocMeaningQueryWrapper = new LambdaQueryWrapper<>();
        vocMeaningQueryWrapper.in(VocMeaningDO::getVocId, list);
        vocMeaningMapper.delete(vocMeaningQueryWrapper);
        // todo:删除单词例句表中例句
        LambdaQueryWrapper<ExampleSentenceDO> exampleSentenceQueryWrapper = new LambdaQueryWrapper<>();
        exampleSentenceQueryWrapper.in(ExampleSentenceDO::getVocId, list);
        exampleSentenceMapper.delete(exampleSentenceQueryWrapper);
        // todo：根据voc_chap_book表对voc_chapter表和voc_book表中voc_count减1，然后删除voc_chap_book表中数据
        LambdaQueryWrapper<VocChapBookDO> vocChapBookQueryWrapper = new LambdaQueryWrapper<>();
        vocChapBookQueryWrapper.in(VocChapBookDO::getVocId, list);
        List<VocChapBookDO> vocChapBookDOs = vocChapBookMapper.selectList(vocChapBookQueryWrapper);
        if (CollectionUtils.isEmpty(vocChapBookDOs)) {
            return vocConverter.toDeleteVocOperateDTOs(vocDOs);
        }
        // todo:修改书籍中单词数量
        LambdaUpdateWrapper<VocBookDO> vocBookUpdateWrapper = new LambdaUpdateWrapper<>();
        vocBookUpdateWrapper.in(VocBookDO::getId,
                        vocChapBookDOs.stream().map(VocChapBookDO::getBookId).collect(Collectors.toList()))
                .setSql("voc_count = voc_count - 1");
        vocBookMapper.update(vocBookUpdateWrapper);
        // todo:修改章节中单词数量
        LambdaUpdateWrapper<VocChapterDO> chapterUpdateWrapper = new LambdaUpdateWrapper<>();
        chapterUpdateWrapper.in(VocChapterDO::getId,
                        vocChapBookDOs.stream().map(VocChapBookDO::getChapterId).collect(Collectors.toList()))
                .setSql("voc_count = voc_count - 1");
        vocChapterMapper.update(chapterUpdateWrapper);
        // todo:删除voc_chap_book中数据
        vocChapBookMapper.delete(vocChapBookQueryWrapper);
        return vocConverter.toDeleteVocOperateDTOs(vocDOs);
    }

    // todo 指定单词的单词-章节-书籍关系列表
    @Override
    public List<VocChapBookDTO> getVocRelations(Long vocId) {

        List<VocChapBookDO> vocChapBookDOs = vocChapBookMapper.selectCategoryIdAndNameByVocId(vocId);
        return vocConverter.vocChapBookDOs2DTOs(vocChapBookDOs);
    }

    // todo 获取书籍单词列表(无章节版)
    @Override
    public PageDTO<DisplayBookVocDTO> getDisplayBookVocsInfo(AppVocPageRequest pageRequest) {

        // todo 当选中一本书通过id来查询该书下的所有单词
        LambdaQueryWrapper<VocChapBookDO> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(VocChapBookDO::getBookId, pageRequest.getBookId());
        List<VocChapBookDO> vocChapBookDOs = vocChapBookMapper.selectList(wrapper1);
        List<Long> vocIds = vocChapBookDOs.stream().map(DO -> DO.getVocId()).filter(Objects::nonNull).distinct().collect(Collectors.toList());

        // todo 获得完整版vocDOs
        List<VocDO> vocDOS = vocMapper.getCompleteVocDetails(vocIds, Long.valueOf(pageRequest.getUserId()));

        return vocConverter.displayBookVocList2Page(vocDOS, (long) vocDOS.size());
    }

    // todo 获取书籍单词列表(有章节版)
    @Override
    public PageDTO<DisplayChapterDTO> getDisplayBookChapterVocsInfo(AppVocPageRequest pageRequest) {
        // todo 获取书籍的所有章节ID
        LambdaQueryWrapper<VocChapBookDO> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(VocChapBookDO::getBookId, pageRequest.getBookId());
        List<VocChapBookDO> vocChapBookDOs = vocChapBookMapper.selectList(wrapper1);

        List<Long> chapterIds = vocChapBookDOs.stream()
                .map(VocChapBookDO::getChapterId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());

        List<VocChapterDO> vocChapterDOS = new ArrayList<>();

        for(Long chapterId : chapterIds) {
            // todo 获取章节基本信息
            VocChapterDO vocChapterDO = vocChapterMapper.selectById(chapterId);
            if(vocChapterDO == null) {
                continue;
            }

            // todo 获取章节下的所有单词ID
            LambdaQueryWrapper<VocChapBookDO> wrapper3 = new LambdaQueryWrapper<>();
            wrapper3.eq(VocChapBookDO::getChapterId, chapterId)
                    .eq(VocChapBookDO::getBookId, pageRequest.getBookId());
            List<Long> vocIds = vocChapBookMapper.selectList(wrapper3).stream()
                    .map(VocChapBookDO::getVocId)
                    .filter(Objects::nonNull)
                    .distinct()
                    .collect(Collectors.toList());

            // todo 获取完整版vocDOs
            List<VocDO> vocDOS = vocMapper.getCompleteVocDetails(
                    vocIds,
                    Long.valueOf(pageRequest.getUserId())
            );

            vocChapterDO.setVocs(vocDOS);
            vocChapterDOS.add(vocChapterDO);
        }

        return vocConverter.displayChapterVocList2Page(vocChapterDOS, (long) vocChapterDOS.size());

    }

    // todo 获取单词详情
    @Override
    public VocDTO getVocDetail(Long vocId, Long userId) {
        VocDO vocDO = vocMapper.getCompleteVocDetail(vocId, userId);
        return vocConverter.vocDO2DTO(vocDO);
    }

    @Override
    public UserBookStatisticsDTO getUserChooseCountInBook(Long userId, Long bookId) {
        return null;
    }

    // todo: HCY 4星级任务 在该service方法中完成Excel文件内容的读取 和 校验上传单词的excel表格 主要代码在excel包下
    @Transactional
    @Override
    @OperateLog(dataType = "Excel文件校验", operateType = OperateLogConstant.OPERATE_EXCEL_ADD)
    public void vocExcelValidate(MultipartFile file) throws IOException {
        // 1.创建用于读取数据的ReadListener对象, 泛型类型表示封装Excel每行数据的实体类
        ReadListener<VocExcelDTO> readListener = new ValidateVocExcelListener(vocBookMapper, vocChapterMapper);

        // 2. 定义用来封装Excel每行数据的实体类的Class对象
        Class<VocExcelDTO> rowClass = VocExcelDTO.class;

        // 3. 调用EeasyExcel类的静态方法read，按行读取Excel文件中的数据
        EasyExcel.read(file.getInputStream(), rowClass, readListener)
                // 指定读取的sheet我们的一个excel只使用默认的一个sheet所以不用指定
                .sheet()
                // 开始读取,方法执行完毕，那么整个Excel文件也读取完了
                .doRead();

    }


    // todo: HCY 4星级任务 通过excel表格上传单词，存储到数据库，主要代码在excel包下
    @Transactional
    @Override
    @OperateLog(dataType = "Excel存储数据库", operateType = OperateLogConstant.OPERATE_EXCEL_ADD)
    public ExcelAddOperateDTO addVocExcel(MultipartFile file, Long userId) throws IOException {

        // 获取文件名
        String fileName = file.getOriginalFilename();

        // 1.创建用于读取数据的ReadListener对象, 泛型类型表示封装Excel每行数据的实体类
        ReadListener<VocExcelDTO> readListener = new VocExcelListener(vocMapper, vocMeaningMapper
                , exampleSentenceMapper, vocChapBookMapper);

        // 2. 定义用来封装Excel每行数据的实体类的Class对象
        Class<VocExcelDTO> rowClass = VocExcelDTO.class;

        // 3. 调用EeasyExcel类的静态方法read，按行读取Excel文件中的数据
        EasyExcel.read(file.getInputStream(), rowClass, readListener)
                // 指定读取的sheet我们的一个excel只使用默认的一个sheet所以不用指定
                .sheet()
                // 开始读取,方法执行完毕，那么整个Excel文件也读取完了
                .doRead();

        // 创建返回对象
        ExcelAddOperateDTO excelAddOperateDTO = new ExcelAddOperateDTO();
        excelAddOperateDTO.setFileName(fileName); // 设置文件名
        excelAddOperateDTO.setTotalCount(((VocExcelListener) readListener).getTotalCount()); // 设置处理条数

        return excelAddOperateDTO;
    }

    // todo 删除单词的音频文件
    @OperateLog(dataType = "单词", operateType = OperateLogConstant.OPERATE_SINGLE_DELETE)
    @Override
    public DeleteVocFileOperateDTO deleteFile(Long id, String type, String name) {

        // todo 三个参数不能为空
        if (id == null || type == null || name == null) {
            throw new BusinessException(ResultCodeEnum.FAIL);
        }

        // todo 初始化返回对象
        VocDO vocDO = vocMapper.selectById(id);
        if (vocDO == null) {
            throw new BusinessException(ResultCodeEnum.VOC_NOT_EXISTED);
        }

        DeleteVocFileOperateDTO result = new DeleteVocFileOperateDTO();
        result.setVocId(id);
        result.setContent(vocDO.getContent());
        result.setType(type);
        result.setFileName(name);

        try {
            // todo 删除文件
            fileUploadService.deleteFile(name);

            LambdaUpdateWrapper<VocDO> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            lambdaUpdateWrapper.eq(VocDO::getId, id);

            // todo type必须为us或uk且name必须根据type和目标单词的音频文件对象名匹配
            if ("uk".equals(type)) {
                if (!name.equals(vocDO.getUkPronounciation().substring(vocDO.getUkPronounciation().lastIndexOf('/') + 1))) {
                    throw new BusinessException(ResultCodeEnum.FAIL);
                }
                lambdaUpdateWrapper.set(VocDO::getUkPronounciation, null);
            } else if ("us".equals(type)) {
                if (!name.equals(vocDO.getUsPronounciation().substring(vocDO.getUsPronounciation().lastIndexOf('/') + 1))) {
                    throw new BusinessException(ResultCodeEnum.FAIL);
                }
                lambdaUpdateWrapper.set(VocDO::getUsPronounciation, null);
            } else {
                throw new BusinessException(ResultCodeEnum.TYPE_NOT_EXIST);
            }
            vocMapper.update(null, lambdaUpdateWrapper);

            return result;
        } catch (Exception e) {
            throw new BusinessException(ResultCodeEnum.FAIL);
        }
    }

    // todo 删除单词与书籍和章节的关系
    @OperateLog(dataType = "单词", operateType = OperateLogConstant.OPERATE_SINGLE_DELETE)
    @Override
    public DeleteVocRelationOperateDTO deleteVocRelation(Long id) {

        // todo 根据关系id判断是否存在
        LambdaQueryWrapper<VocChapBookDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(VocChapBookDO::getId, id);

        VocChapBookDO vocChapBookDO = vocChapBookMapper.selectOne(lambdaQueryWrapper);
        if (vocChapBookDO == null) {
            throw new BusinessException("单词-书籍-章节表voc_chap_book没有该记录哦！", 6052);
        }

        // todo voc_book书籍和所属类目关系表的voc_count: 该书籍所包含的单词数 -1
        LambdaUpdateWrapper<VocBookDO> lambdaUpdateWrapper1 = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper1.eq(VocBookDO::getId, vocChapBookDO.getBookId())
                .setSql("voc_count = voc_count - 1");
        vocBookMapper.update(null, lambdaUpdateWrapper1);

        // todo voc_chapter章节和所属书籍关系表的voc_count: 该章节所包含的单词 -1
        LambdaUpdateWrapper<VocChapterDO> lambdaUpdateWrapper2 = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper2.eq(VocChapterDO::getId, vocChapBookDO.getChapterId())
                .setSql("voc_count = voc_count - 1");
        vocChapterMapper.update(null, lambdaUpdateWrapper2);

        // todo 逻辑删除关系表这条记录
        vocChapBookMapper.deleteById(id);

        return vocConverter.toDeleteVocRelationOperateDTO(vocChapBookDO);
    }

    // todo 删除单词释义
    @OperateLog(dataType = "单词", operateType = OperateLogConstant.OPERATE_SINGLE_DELETE)
    @Override
    public DeleteInterpretationOperateDTO deleteInterpretation(Long id) {

        // todo 根据关系id判断是否存在
        LambdaQueryWrapper<VocMeaningDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(VocMeaningDO::getId, id);

        VocMeaningDO vocMeaningDO = vocMeaningMapper.selectOne(lambdaQueryWrapper);
        if (vocMeaningDO == null) {
            throw new BusinessException("单词-释义表voc_meaning没有该记录哦！", 6053);
        }
        vocMeaningMapper.deleteById(id);

        // todo 根据关系表获取单词id, 到单词表里找到单词content
        Long vocId = vocMeaningDO.getVocId();
        LambdaQueryWrapper<VocDO> lambdaQueryWrapper2 = new LambdaQueryWrapper<>();
        lambdaQueryWrapper2.eq(VocDO::getId, vocId);
        VocDO vocDO = vocMapper.selectOne(lambdaQueryWrapper2);

        return vocConverter.toDeleteInterpretationOperateDTO(vocMeaningDO, vocDO.getContent());
    }

    // todo 删除单词的例句
    @OperateLog(dataType = "单词", operateType = OperateLogConstant.OPERATE_SINGLE_DELETE)
    @Override
    public DeleteVocExampleOperateDTO deleteExample(Long id) {

        LambdaQueryWrapper<ExampleSentenceDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(ExampleSentenceDO::getId, id);
        ExampleSentenceDO sentenceDO = exampleSentenceMapper.selectOne(lambdaQueryWrapper);
        if (sentenceDO == null) {
            throw new BusinessException("例句表example_sentence没有该记录哦", 6054);
        }
        exampleSentenceMapper.deleteById(id);

        Long vocId = sentenceDO.getVocId();
        LambdaQueryWrapper<VocDO> vocDOLambdaQueryWrapper = new LambdaQueryWrapper<>();
        vocDOLambdaQueryWrapper.eq(VocDO::getId, vocId);
        VocDO vocDO = vocMapper.selectOne(vocDOLambdaQueryWrapper);

        return vocConverter.toDeleteExampleOperateDTO(sentenceDO, vocDO.getContent());
    }
}
